<template>
	<article class="page page-rename-by-namepool">
		<h4 class="text-center">基于名称池重命名文件</h4>
		<form class="page-body">
			<div class="row">
				<div class="col-3 left">
					<fieldset>
						<legend>参数配置</legend>
						<div class="fieldset-content">
							<div class="form-group">
								<label class="col-form-label">本地读取</label>
								<input class="form-control" type="file" multiple @change="fileChange" placeholder="请选择文件" />
							</div>
							<div class="form-group form-group-main">
								<label class="col-form-label">名称池(共 {{namesPoolList.length}} 个)</label>
								<textarea class="form-control" v-model.trim="namesPool" placeholder="请输入要使用的文件名称，以“回车”分隔"></textarea>
							</div>
							<div class="form-group">
								<x-button type="default" block @click="preview" :disabled="loadingCount > 0">预览</x-button>
							</div>
							<div class="form-group">
								<x-button type="primary" block @click="execute" :loading="loadingCount > 0">执行修改</x-button>
							</div>
						</div>
					</fieldset>
				</div>
				<div class="col-9 right">
					<fieldset>
						<legend>文件列表</legend>
						<div class="fieldset-content">
							<div class="row-flex" align="center">
								<div class="row-flex-main text-left">共 {{filesList.length}} 个文件</div>
								<div class="row-flex-suffix">
									<button type="button" class="btn btn-link" @click="clearFilesList" title="清空">
										<i class="fa fa-trash-o"></i>
									</button>
								</div>
							</div>
							<div class="table-header" :style="thStyles">
								<table>
									<tbody>
										<tr>
											<th v-for="(v,i) in tableHeaders" :key="`th_${i}`" :style="{width: v.width}">{{v.label}}</th>
										</tr>
									</tbody>
								</table>
							</div>
							<div class="table-body" @drop.prevent="filesDrop" @dragover.prevent>
								<table ref="table">
									<tbody>
										<tr v-for="(v,i) in filesList" :key="`file_${i}`">
											<template v-for="(item,index) in tableHeaders">
												<td :style="{width: item.width}" :key="`td_${i}_${index}`">
													<button v-if="item.value==='action'" type="button" class="btn btn-link" @click="deleteFileItem(i)" title="删除">
														<i class="fa fa-close"></i>
													</button>
													<span v-else>{{v[item.value] || ''}}</span>
												</td>
											</template>
										</tr>
										<tr v-if="filesList.length===0" class="nodata-tr"><td>将待处理的文件拖动到此处</td></tr>
									</tbody>
								</table>
							</div>
						</div>
					</fieldset>
				</div>
			</div>
		</form>
	</article>
</template>

<script>
const fs = global.require('fs')
const path = global.require('path')

export default {
	name: 'rename-by-namepool',
	data () {
		return {
      filesList: [],
      tasksList: [],
      tableHeaders: [
        {label: '原文件名', value: 'oldName', width: '30%'},
        {label: '新文件名', value: 'newName', width: '30%'},
        {label: '状态', value: 'status', width: '20%'},
        {label: '操作', value: 'action', width: '20%'},
      ],
      thStyles: {},
			namesPool: '',
			loadingCount: 0
		}
	},
  computed: {
		namesPoolList () {
			let result = []
			result = this.namesPool.split('\n')
			result = result.filter(v => !!v)
			return result
		},
    filePathsList () {
      return this.filesList.map(v => v.path)
    }
  },
	methods: {
    fileChange (e) {
      if (!e.target.files) {
        return this.$toast('未找到有效文件！')
      }
			let files = [...e.target.files]
			let result = []
			files.forEach(v => {
				result.push(v.name)
			})
			if (this.namesPool) {
				this.namesPool += '\n'
			}
			this.namesPool += result.join('\n')
    },
    // 拖拽待处理文件
    filesDrop (e) {
      const filesList = e.dataTransfer.files
      if (!filesList) return
      for (let i = 0; i < filesList.length; i++) {
        const file = filesList[i]
        if (!this.filePathsList.includes(file.path)) {
          let fileStat = fs.statSync(file.path)
          let oldName = path.basename(file.path) || file.name
          this.filesList.push({
            path: file.path,
            oldName,
            newName: '',
            dirName: path.dirname(file.path),
            status: '',
            updateTime: fileStat.mtime,
            createTime: fileStat.birthtime,
          })
        }
      }
      this.checkScroll()
    },
    // 删除条目
    deleteFileItem (index) {
      this.filesList.splice(index, 1)
      this.checkScroll()
    },
    checkScroll () {
      this.$nextTick(() => {
        if (!this.$refs.table) return
        let tableHeight = this.$refs.table.clientHeight
        let tableParentHeight = this.$refs.table.parentNode.clientHeight
        if (tableHeight > tableParentHeight) {
          this.thStyles = {overflow: 'hidden scroll'}
        } else {
          this.thStyles = {overflow: 'hidden'}
        }
      })
    },
    // 清空待处理文件
    clearFilesList () {
      this.filesList = []
      this.tasksList = []
      this.thStyles = {}
      this.loadingCount = 0
    },
    // 预览
    preview () {
      if (!this.namesPoolList.length) {
        this.$toast('名称池不能为空')
				return false
      }
      if (!this.filesList.length) {
        this.$toast('未找到待处理的文件')
				return false
      }
			let filesList = this.$jstools.deepCopy(this.filesList)
			this.filesList = filesList.map((v, i) => {
				v.newName = this.namesPoolList[i] || ''
				v.status = ''
				return v
			})
			return true
    },
    // 执行修改
    execute () {
			if (!this.preview()) return
      this.filesList.forEach((v, i) => {
        let newPath = path.join(v.dirName, v.newName)
        if (v.oldName === v.newName || !v.newName) return
        this.loadingCount++
        this.tasksList.push(
          this.rename(v.path, newPath).then(() => {
            this.$set(this.filesList[i], 'status', '修改成功')
            this.$set(this.filesList[i], 'oldName', v.newName)
            this.$set(this.filesList[i], 'newName', '')
            this.$set(this.filesList[i], 'path', newPath)
          }).catch((err) => {
            console.log(err)
            this.$set(this.filesList[i], 'status', '修改失败')
          }).finally(() => {
            this.loadingCount--
          })
        )
      })
      Promise.all(this.tasksList).finally(() => {
        this.tasksList = []
      })
    },
    // 重命名
    rename (from, to) {
      return new Promise((resolve, reject) => {
        fs.rename(from, to, (err) => {
          if (err) {reject(err)}
          else {resolve()}
        })
      })
    }
	},
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";
.page-rename-by-namepool {
	display: flex;
	flex-direction: column;
	fieldset {
		height: 100%;
		.fieldset-content {
			height: calc(100% - 2em);
			display: flex;
			flex-direction: column;
		}
	}
	.page-body {
		height: 0;
		flex-grow: 1;
		& > .row {
			height: 100%;
		}
		.left {
			.form-group-main {
				flex-grow: 1;
				display: flex;
				flex-direction: column;
				textarea {
					flex-grow: 1;
				}
			}
		}
		.right {
			.table-header,
			.table-body {
				table {
					width: 100%;
					border: 1px solid @borderGrey;
					tr {height: 2em;}
					th, td {
						border: 1px solid @borderGrey;
						text-align: center;
						vertical-align: middle;
					}
					.nodata-tr {
						height: 100%;
						font-size: 16px;
						color: #999;
					}
				}
			}
			.table-body {
				height: 0;
				flex-grow: 1;
				overflow: auto;
				table {
					min-height: 100%;
				}
			}
		}
	}
}
</style>
